package cn.edu.ahu.aircondition.modbus.service.util;

import com.serotonin.modbus4j.ModbusFactory;
import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.exception.ModbusInitException;
import com.serotonin.modbus4j.exception.ModbusTransportException;
import com.serotonin.modbus4j.ip.IpParameters;
import com.serotonin.modbus4j.msg.WriteRegistersRequest;
import com.serotonin.modbus4j.msg.WriteRegistersResponse;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.util.*;

/**
 *
 * Created by ahu on 2017/6/6.
 */
public class ModbusReadAWriteUtil {
    private String address;
    private Integer port;
    private Integer unitId;


    public ModbusReadAWriteUtil() throws IOException {
        Properties prop = new Properties();
        InputStream in = new BufferedInputStream(new FileInputStream("src\\main\\resource\\config.properties"));
        prop.load(in);
        this.address = prop.getProperty("url");
        this.port = 502;
        this.unitId = 1;
    }

    public ModbusReadAWriteUtil(String address, int port, int unitId) {
        this.address = address;
        this.port = port;
        this.unitId = unitId;
    }

//    /**
//     * 通过TCP的方式获取modbus的内容,读取数据
//     * @param functionCode modbus功能码
//     * @param startNum 起始寄存器地址
//     * @param dataLength 期望数据长度
//     * @return 获取的modbus内容
//     */
//    public List<Integer> ReadModbusByTCP(Integer functionCode, Integer startNum, Integer dataLength){
//        try {
//            List<ModbusRequest> requestList = getRequestList(functionCode,startNum,dataLength);
//            return getResponseByTCP(generateTransaction(),requestList);
//        } catch (Exception e) {
//            e.printStackTrace();
//            return null;
//        }
//    }

    public boolean WriteModbusByTCP (TreeMap<Integer,Integer> dataMap) throws Exception {
        short[] values = new short[dataMap.size()];
        Integer integer = 0;
        Integer startNum = 0;
        for(Integer map :dataMap.keySet()){
            values[integer] =  dataMap.get(map).shortValue();
            integer++;
            if (map > startNum){//取出最大值
                startNum = map;
            }
        }
        startNum = startNum -dataMap.size() +1;
        IpParameters ipParameters = new IpParameters();
        ipParameters.setHost("172.20.12.124");
        ipParameters.setPort(502);
        ModbusFactory modbusFactory = new ModbusFactory();
        ModbusMaster master = modbusFactory.createTcpMaster(ipParameters,true);
        master.setTimeout(1000);
        master.init();
        try {
            WriteRegistersRequest request = new WriteRegistersRequest(1, startNum, values);
            WriteRegistersResponse response = (WriteRegistersResponse) master.send(request);
            master.destroy();
            Thread.sleep(300);
            return !response.isException();
        }
        catch (ModbusTransportException e) {
            e.printStackTrace();
            return false;
        }
    }

//    /**
//     * 为Modbus连接生成Transaction；
//     * @return 根据TCP属性生成的Transaction；
//     * @throws Exception 异常
//     */
//    private TCPMasterConnection generateTransaction() throws Exception{
//        InetAddress addy = InetAddress.getByName(this.address);
//        TCPMasterConnection connection = new TCPMasterConnection(addy);
//        connection.setTimeout(3000);
//        connection.setPort(port);
//        System.out.println("Trying to connect to "+addy.getCanonicalHostName()+" on port "+port);
//        connection.connect();
//
//        return connection;
//    }
//
//    /**
//     * 根据request获取response
//     *
//     * @param requestList 服务器的请求组
//     * @return 根据请求组获取的完整的数据结果
//     * @throws ModbusException
//     */
//    private List<Integer> getResponseByTCP( TCPMasterConnection connection, List<ModbusRequest> requestList)
//            throws ModbusException {
//        ModbusTCPTransaction transaction = new ModbusTCPTransaction(connection);
//        List<Integer> dataResult = new ArrayList<Integer>();
//        if (requestList == null) {
//            System.out.println("TCP请求无返回值");
//            return null;
//        }
//        for (ModbusRequest request : requestList) {
//            if (request != null) {
//                request.setUnitID(unitId);
//                request.setTransactionID(1);
//            }
//            transaction.setRequest(request);
//            transaction.execute();
//            ModbusResponse response = transaction.getResponse();
//            dataResult.addAll(getResponse(response));
//        }
//        connection.close();
//        return dataResult;
//    }
//
//    /**
//     * 获取下位机的Response结果。（未使用Hashmap原因：有大概率发生丢包）
//     * @param response Response请求
//     * @return Response数据组
//     */
//    private List<Integer> getResponse(ModbusResponse response){
//        List<Integer> dataResult = new ArrayList<Integer>();
//        /**
//         * functionCode == 1时，获取Read Coils数据
//         */
//        if (response instanceof ReadCoilsResponse) {
//            ReadCoilsResponse res = (ReadCoilsResponse)response;
//            for (Byte coil:res.getCoils().getBytes()){
//                dataResult.add(Integer.bitCount(coil));
//            }
//        }
//        /**
//         * functionCode == 4时，获取Input Registers数据
//         * 寄存器地址为3X
//         */
//        if (response instanceof ReadInputRegistersResponse) {
//            ReadInputRegistersResponse res = (ReadInputRegistersResponse)response;
//            dataResult.add(res.getRegisterValue(0));
//        }
//        /**
//         * functionCode == 3时，获取Input Registers数据
//         * 寄存器地址为4X
//         */
//        if (response instanceof ReadMultipleRegistersResponse) {
//            ReadMultipleRegistersResponse res = (ReadMultipleRegistersResponse) response;
//            dataResult.add(res.getRegisterValue(0));
//        }
//        /**
//         * functionCode == 6时，将数据写入寄存器中，并获取寄存器中的数据
//         */
//        if (response instanceof WriteSingleRegisterResponse){
//            WriteSingleRegisterResponse res = (WriteSingleRegisterResponse)response;
//            dataResult.add(res.getRegisterValue());
//        }
//        return dataResult;
//    }
//
//    /**
//     * 根据功能码，起始寄存器地址以及数据长度生成ModbusRequest队列，供TCP数据交互使用。
//     * 完成读操作。
//     * @param functionCode modbus功能码；
//     * @param startNum 起始寄存器地址；
//     * @param dataLength 获取的数据长度；
//     * @return ModbusRequest队列
//     */
//    private List<ModbusRequest> getRequestList(Integer functionCode,Integer startNum, Integer dataLength) {
//        List<ModbusRequest> modbusRequest =new ArrayList<ModbusRequest>();
//        if (functionCode == 1){
//            modbusRequest.add(getRequest(functionCode,startNum));
//        }
//        else {
//            for (int i = 0;i<dataLength;i++)
//                modbusRequest.add(getRequest(functionCode,startNum+i));
//        }
//        return modbusRequest;
//    }
//
//    /**
//     * 根据hashmap的数据，对寄存器进行写操作；
//     * @param functionCode 功能码（写操作一般为6）；
//     * @param dataMap key：寄存器地址；value：写入寄存器的值；
//     * @return
//     */
//    private List<ModbusRequest> getRequestList(Integer functionCode, TreeMap<Integer,Integer> dataMap) {
//        List<ModbusRequest> modbusRequest =new ArrayList<ModbusRequest>();
//        Integer startNum = 0;
//        for (Integer map :dataMap.keySet()){
//            if (startNum < map){
//                startNum = map;
//            }
//        }
//        modbusRequest.add(getRequest(functionCode,startNum,dataMap));
//        return modbusRequest;
//    }
//
//    private ModbusRequest getRequest(Integer functionCode,Integer startNum) {
//        //Note: simple process image uses 0-based register addresses
//        switch (functionCode) {
//            case 1://0X,00000+
//                return new ReadCoilsRequest(startNum,1);
//            case 2:
//                return new ReadInputDiscretesRequest(startNum,1);
//            case 4://3X,30000+
//                return new ReadInputRegistersRequest(startNum,1);
//            case 3://4X,40000+
//                return new ReadMultipleRegistersRequest(startNum,1);
//            default:
//                return null;
//        }
//    }
//
//    private ModbusRequest getRequest(Integer functionCode,Integer startNum,TreeMap<Integer,Integer> dataMap) {
//        //Note: simple process image uses 0-based register addresses
//        Register[] registers = new Register[dataMap.size()];
//        Integer i = 0;
//        for(Integer regData:dataMap.keySet()){
//            Register r = ModbusCoupler.getReference().getProcessImageFactory().createRegister();
//            r.setValue(dataMap.get(regData));
//            registers[i] = r;
//            i++;
//        }
//        switch (functionCode) {
////            case 6://写单个寄存器
////                return new WriteSingleRegisterRequest(startNum,r);
//            case 16://写多个保持寄存器
//                return new WriteMultipleRegistersRequest(startNum,registers);
//            default:
//                return null;
//        }
//    }
}
